package edu.etu.sob.model.impl;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;

import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.Restriction;
import com.hp.hpl.jena.ontology.UnionClass;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;

import edu.etu.sob.model.IOntClassDesc;
import edu.etu.sob.model.IRestrictionDesc;
import edu.etu.sob.util.OntUtils;

@XmlRootElement(name="ontclass")
public class OntClassDesc extends OntResourceDesc implements IOntClassDesc {

	@XmlElements({
			@XmlElement(name="ontclass", type=OntClassDesc.class),
			@XmlElement(name="lit_rest", type=LiteralRestriction.class),
			@XmlElement(name="res_rest", type=ResourceRestriction.class)
	})
	private List<OntClassDesc> superClass;
	
	public List<OntClassDesc> getSuperClass() {
		if (superClass == null)
			superClass = new ArrayList<OntClassDesc>();
		return superClass;
	}

	public OntClassDesc() {
	}
	
	public OntClassDesc(Resource c) {
		super(c);
	}
	
	@Override
	public boolean isRestriction() {
		return (getType() == 2) || (getType() == 3);
	}
	
	@Override
	public int getType() {
		return 1;
	}

	@Override
	public IRestrictionDesc asRestriction() {
		return (IRestrictionDesc) this;
	}
	
	@Override
	public void addSuperClasses(ExtendedIterator<OntClass> superClasses) {
		while(superClasses.hasNext()) {
			OntClass c = superClasses.next();
			getSuperClass().add(addClassDesc(c));
		}
	}

	private OntClassDesc addClassDesc(OntClass c) {
		OntClassDesc ontClassDesc = new OntClassDesc();
		if (c.isUnionClass()) {
//			OntClassDesc bc = addBooleanClass(c.asUnionClass());
//			ontClassDesc.getSuperClassesList().add(bc);
		} else if (c.isIntersectionClass()) {
//			OntClassDesc bc = addBooleanClass(c.asIntersectionClass());
//			ontClassDesc.getSuperClassesList().add(bc);
		} else if (c.isComplementClass()) {
//			addBooleanClass(c.asComplementClass());
		} else if (c.isRestriction()) {
            RestrictionDesc r = renderRestriction( c.asRestriction() );
            return r;
        } else {
			if (!c.isAnon()) {
				String uri = c.getURI();
				ontClassDesc.setUri(uri);
				ontClassDesc.setShortName(OntUtils.getShortName(c, uri));
			}
			else {
				ontClassDesc.setId(c.getId().toString());
				ontClassDesc.setAnon(true);
			}
        }
		return ontClassDesc;
	}

	// TODO needs refactoring
	private RestrictionDesc renderRestriction(Restriction restriction) {
		// TODO needs a better check
		RDFNode value = null;
		int rtype = -1;
		if (restriction.isAllValuesFromRestriction()) {
			value = restriction.asAllValuesFromRestriction().getAllValuesFrom();
			rtype = 0;
		} else if(restriction.isSomeValuesFromRestriction()) {
			value = restriction.asSomeValuesFromRestriction().getSomeValuesFrom();
			rtype = 1;
		} else if(restriction.isHasValueRestriction()) {
			value = restriction.asHasValueRestriction().getHasValue();
			rtype = 2;
		}

		boolean isLiteral = value instanceof Literal;
		RestrictionDesc r = isLiteral ? new LiteralRestriction() : new ResourceRestriction();
		
		r.setRestrictionType(rtype);
		
		if (!restriction.isAnon()) {
			r.setUri(restriction.getURI());
			r.setShortName(OntUtils.getShortName(restriction, r.getUri()));
		} else {
			r.setAnon(true);
			r.setId(restriction.getId().toString());
		}
		
		r.setOnProperty(new OntResourceDesc(restriction.getOnProperty()));
		
		
		if (isLiteral)
			((LiteralRestriction)r).setValue(((Literal) value).getLexicalForm());
		else {
			((ResourceRestriction)r).setValue(new OntResourceDesc((Resource) value));
		}
		
		return r;
	}

	private OntClassDesc addBooleanClass(UnionClass unionClass) {
		return null;
	}
}
